﻿using SalesSys.DAL.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using SalesSys.BLL;
using SalesSys.BLL.Depot;
using SalesSys.Comm.Utility;
using SalesSys.Comm.DAL;
using SalesSys.BLL.Sales;

namespace SalesSys.Service.Purchasing
{
    public interface IPurchasingSvc
    {
        /// <summary>
        /// 设置商品价格信息
        /// </summary>
        /// <param name="purchase"></param>
        IResultState SetPurchasingPrice(Guid handlerId, PurchaseOrder purchase);
        /// <summary>
        /// 设置商品信息
        /// </summary>
        /// <param name="purchase"></param>
        IResultState SetWeightAndPrice(Guid handlerId, PurchaseOrder purchase);
        /// <summary>
        /// 创建采购单申请，并提交审批
        /// </summary>
        /// <param name="purchaseOrder"></param>
        /// <returns></returns>
        IResultState Create(PurchaseOrder purchaseOrder);

        /// <summary>
        ///  确认采购完成
        /// </summary>
        /// <param name="handlerId"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IResultState PurchaseComplete(IEmployee handlerId, Guid orderId);

        /// <summary>
        /// 采购单入库，依据采购单实际重量
        /// </summary>
        /// <param name="purchaseOrderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 获取原计划单
        /// 判断是否可以转入库单
        /// 根据计划单实际重量及价格入库
        /// </remarks>
        IResultState PurchasingEntry(Guid purchaseOrderId);

        KeyValuePair<int, IEnumerable<PurchaseOrder>> GetList(string name, PurchaseOrder.PurchaseState? state, Guid? createrId = null,
            int page = 1, int rows = 10);

        /// <summary>
        /// 查询负责人管辖范围内的采购单
        /// </summary>
        /// <param name="name">模糊查询</param>
        /// <param name="createTime">创建时间</param>
        /// <param name="state">状态</param>
        /// <param name="managerId">负责人编号</param>
        /// <param name="page">分页</param>
        /// <param name="rows">每页显示条数</param>
        /// <returns></returns>
        KeyValuePair<int, IEnumerable<PurchaseOrder>> GetDirectorList(string name, DateTime? createTime, PurchaseOrder.PurchaseState? state, Guid? managerId = null,
            int page = 1, int rows = 10);


        /// <summary>
        /// 直发采购完成
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IResultState SalePurchaseComplete(IEmployee handler, Guid pId);

        /// <summary>
        /// 直发销售采购单，基础信息编辑
        /// </summary>
        /// <param name="po"></param>
        /// <returns></returns>
        IResultState SalePurchaseEdit(Guid handlerId, PurchaseOrder po);
        /// <summary>
        ///  获取采购报表数据
        /// </summary>
        /// <param name="providerName">厂家名称</param>
        /// <param name="createTime">创建时间</param>
        /// <param name="state">订单状态</param>
        /// <param name="page"></param>
        /// <param name="rows"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        string[][] GetPurchaseReportArray(string providerName, DateTime? createTime, DAL.Models.PurchaseOrder.PurchaseState? state, int page, int rows, out int count);

        /// <summary>
        /// 采购单取消
        /// </summary>
        /// <param name="handler"></param>
        /// <param name="orderId"></param>
        /// <returns></returns>
        IResultState PurchaseCancel(IEmployee handler, Guid orderId);
    }
    public class PurchasingSvc : BaseBLL<PurchaseOrder, Guid>, IPurchasingSvc
    {
        private IDepotBLL depotBll = new DepotBLL();
        private CommodityBLL commodityBll = new CommodityBLL();
        private ProviderBLL providerBll = new ProviderBLL();
        private IOrderBLL orderBll = new OrderBLL();

        /// <summary>
        /// 规范价是否以标件为准
        /// </summary>
        private bool NormPriceIsStandard = false;



        /// <summary>
        /// 设置商品价格信息
        /// </summary>
        /// <param name="purchase"></param>
        /// <remarks>
        /// </remarks>
        public IResultState SetPurchasingPrice(Guid handlerId, PurchaseOrder purchase)
        {
            var old = Rep.Find(purchase.Id);
            EmployeeBLL empBll = new EmployeeBLL();
            var emp = empBll.Details(handlerId);

            IResultState resultState = HandlePrice(purchase.Goodses, old);
            if (resultState != null) return resultState;
            old.Total = old.Goodses.Sum(p => p.Price * p.Weight);
            old.Records.Add(new PurchaseRecord()
            {
                Remarks = "订单商品价格修改",
                Type = PurchaseRecordType.Edit,
                HandlerName = emp.Name
            });
            Rep.Update(old);
            return ReState.Success.Create();
        }

        private IResultState HandlePrice(IEnumerable<PurchaseGoods> goodses, PurchaseOrder old)
        {
            decimal nonstan = 0;
            if (old.IsStandard != NormPriceIsStandard)
            {
                nonstan = old.Provider.PurchasingNonstandard;
            }
            foreach (var item in goodses)
            {
                var oldItem = old.Goodses.FirstOrDefault(p => p.Id == item.Id);
                if (oldItem == null)
                {
                    {

                        return ReState.ArgError.Create("错误商品信息");
                    }
                }
                oldItem.Price = item.Price;
                oldItem.NormPrice = oldItem.Price - nonstan;
            }
            return null;
        }

        /// <summary>
        /// 创建采购单
        /// </summary>
        /// <param name="purchaseOrder"></param>
        /// <returns></returns>
        /// <remarks>
        /// 判断户头是否私户
        /// 设置运费户头
        /// 计算标准价
        /// </remarks>
        public new IResultState Create(PurchaseOrder purchaseOrder)
        {
            try
            {
                using (var tran = new TransactionScope())
                {
                    var account = purchaseOrder.Account;
                    decimal nonstan = 0;
                    purchaseOrder.Provider = providerBll.Details(purchaseOrder.Provider.Id);
                    purchaseOrder.ToDepot = providerBll.Details(purchaseOrder.ToDepot.Id);
                    if (purchaseOrder.Provider == null || purchaseOrder.ToDepot == null)
                    {
                        return ReState.ArgError.Create("不存在的供应商或仓库");
                    }
                    if (purchaseOrder.IsStandard != NormPriceIsStandard)
                    {
                        nonstan = purchaseOrder.Provider.PurchasingNonstandard;
                    }
                    foreach (var goods in purchaseOrder.Goodses)
                    {
                        goods.Commodity = commodityBll.Details(goods.Id);
                        goods.NormPrice = goods.Price - nonstan;
                        goods.Order = purchaseOrder;
                        goods.Records = null;
                        goods.SourcePrice = goods.Price;
                        goods.SourceWeight = goods.Weight;
                        // Modify By MYL添加总重量计算
                        goods.Weight = goods.Count * goods.Commodity.Weight;
                        goods.Id = Guid.NewGuid();
                    }
                    purchaseOrder.CalcNew();

                    purchaseOrder.DeliveryPriceTotal = purchaseOrder.DeliveryPrice * purchaseOrder.Goodses.Sum(p => p.Weight);

                    //float fDeliveryPriceTotalTemp = purchaseOrder.DeliveryPriceTotal;
                    //float fDeliveryPriceTotalCalc = purchaseOrder.DeliveryPrice*purchaseOrder.Goodses.Sum(p => p.Weight);
                    //if (!fDeliveryPriceTotalTemp.Equals(fDeliveryPriceTotalCalc))
                    //{
                    //    return ReState.ArgError.Create("运费计算错误");
                    //}


                    Rep.Insert(purchaseOrder);

                    SubmitApproval(purchaseOrder.Id);
                    tran.Complete();
                    return ReState.Success.Create();
                }
            }
            catch (Exception ex)
            {
                return ReState.Error.Create(ex.Message);
            }
        }
        /// <summary>
        /// 提交审批
        /// </summary>
        /// <param name="purchaseOrderId"></param>
        public void SubmitApproval(Guid purchaseOrderId)
        {

            var seq = new SequenceApprovalBLL.PurchasingApproval();
            var purchaseOrder = Details(purchaseOrderId);
            if (purchaseOrder.State != PurchaseOrder.PurchaseState.Pending)
            {
                throw new ArgumentException("提交审批状态错误");
            }
            purchaseOrder.State = PurchaseOrder.PurchaseState.Approval;
            seq.Submit(purchaseOrder, purchaseOrder.Creater);
        }

        static PurchasingSvc()
        {
            SequenceApprovalBLL.PurchasingApproval.ApprovalEndHandle += PurchasingApproval_ApprovalEndHandle;
        }

        static void PurchasingApproval_ApprovalEndHandle(Guid arg1, bool arg2, string msg)
        {
            var svc = new PurchasingSvc();
            var pur = svc.Details(arg1);
            if (arg2)
            {
                pur.State = PurchaseOrder.PurchaseState.Purchasing;
            }
            else
            {
                pur.State = PurchaseOrder.PurchaseState.Cancel;

            }
            AddPurchaseRecord(null, pur, PurchaseRecordType.ApprovalChange);
            svc.Edit(pur);
        }

        public KeyValuePair<int, IEnumerable<DAL.Models.PurchaseOrder>> GetList(string name,
            DAL.Models.PurchaseOrder.PurchaseState? state, Guid? createrId, int page, int rows)
        {
            var query = Rep.Entities;
            if (!string.IsNullOrWhiteSpace(name))
            {
                query = query.Where(p => p.Contact.Contains(name) || p.Creater.Name.Contains(name) || p.Provider.Name.Contains(name));
            }
            if (state != null)
            {
                query = query.Where(p => p.State == state);
            }
            if (createrId != null)
            {
                query = query.Where(p => p.Creater.Id == createrId);
            }
            var count = query.Count();
            var list = query.OrderByDescending(p => p.CreateTime).Paging(page, rows).ToArray();
            return new KeyValuePair<int, IEnumerable<PurchaseOrder>>(count, list);

        }
        public KeyValuePair<int, IEnumerable<DAL.Models.PurchaseOrder>> GetDirectorList(string name, DateTime? createTime,
            DAL.Models.PurchaseOrder.PurchaseState? state, Guid? managerId, int page, int rows)
        {
            var query = Rep.Entities;
            if (!string.IsNullOrWhiteSpace(name))
            {
                query = query.Where(p => p.Contact.Contains(name) || p.Creater.Name.Contains(name) || p.Provider.Name.Contains(name));
            }
            if (state != null)
            {
                query = query.Where(p => p.State == state);
            }
            if (managerId != null)
            {
                query = query.Where(p => p.Provider.Manager.Id == managerId);
            }
            if (createTime != null)
            {
                var day = createTime.Value;
                var addDay = day.AddDays(1);
                query = query.Where(p => p.CreateTime >= day && p.CreateTime < addDay);
            }
            var count = query.Count();
            var list = query.OrderByDescending(p => p.CreateTime).Paging(page, rows).ToArray();
            return new KeyValuePair<int, IEnumerable<PurchaseOrder>>(count, list);

        }

        public string[][] GetPurchaseReportArray(string name, DateTime? createTime, DAL.Models.PurchaseOrder.PurchaseState? state, int page, int rows, out int count)
        {
            var goodsRep = RepositoryFactory.GetRepositoryByFactoryUnit<IRepository<PurchaseGoods>>();
            var query = goodsRep.Entities.Where(p => p.Order != null);
            if (!string.IsNullOrWhiteSpace(name))
            {
                query = query.Where(p => p.Commodity.Supplier.Name.Contains(name));
            }

            if (createTime != null)
            {
                var day = createTime.Value;
                var addDay = day.AddDays(1);
                query = query.Where(p => p.Order.CreateTime >= day && p.Order.CreateTime < addDay);
            }
            count = query.Count();
            var list = query.OrderByDescending(p => p.Order.CreateTime).Paging(page, rows).ToArray().Select(p => new string[] { 
               p.Order.CreateTime.ToString(), p.Commodity.Supplier.Name, p.Commodity.Name, p.Order.IsStandard?"标件":"非标", p.Commodity.Format,
               string.Format("{0:f3}",p.Weight), string.Format("{0:f2}", p.Price),
               string.Format("{0:f2}", (p.Weight*p.Price)) , 
               p.Order.ToDepot == null?"": p.Order.ToDepot.Name,
               p.Order.Account, p.Order.Provider.Name, p.Order.Remarks
             }).ToArray();
            return list;
        }


        /// <summary>
        /// 采购单入库，依据采购单实际重量
        /// </summary>
        /// <param name="purchaseOrderDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// 获取原计划单
        /// 判断是否可以转入库单
        /// 根据计划单实际重量及价格入库
        /// </remarks>
        public IResultState PurchasingEntry(Guid purchaseOrderId)
        {
            var old = Rep.Find(purchaseOrderId);
            if (old == null)
            {
                return ReState.ArgError.Create("无法找到的采购单");
            }
            if (old.State != PurchaseOrder.PurchaseState.Complete)
            {
                return ReState.ArgError.Create("采购单状态错误");
            }
            depotBll.PurchasingEntry(old);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 直发采购完成
        /// </summary>
        /// <param name="handler">操作人</param>
        /// <param name="orderId">采购单编号</param>
        /// <returns></returns>
        public IResultState SalePurchaseComplete(IEmployee handler, Guid pId)
        {
            var order = Rep.Find(pId);
            if (order.PurchaseType != PurchaseType.Sale)
            {
                return ReState.ArgError.Create("当前订单不是直发采购");
            }
            order.State = PurchaseOrder.PurchaseState.Complete;
            AddPurchaseRecord(handler, order, PurchaseRecordType.StateChange);
            Rep.Update(order);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 直发销售采购单， 
        /// </summary>
        /// <param name="handlerId">操作人编号</param>
        /// <param name="po">采购单实体</param>
        /// <returns></returns>
        public IResultState SalePurchaseEdit(Guid handlerId, PurchaseOrder po)
        {
            using (var tran = new TransactionScope())
            {
                var old = Rep.Find(po.Id);
                old.Contact = po.Contact;
                old.DeliveryPrice = po.DeliveryPrice;
                old.District = po.District;
                old.IsPublicDelivery = po.IsPublicDelivery;
                old.IsStandard = po.IsStandard;
                old.Remarks = po.Remarks;
                old.State = PurchaseOrder.PurchaseState.Purchasing;
                Rep.Update(old);
                SetWeightAndPrice(handlerId, po);
                tran.Complete();
            }
            return ReState.Success.Create();
        }

        /// <summary>
        /// 采购单完成确认
        /// </summary>
        /// <param name="handler">操作人编号</param>
        /// <param name="orderId">采购单编号</param>
        /// <returns></returns>
        public IResultState PurchaseComplete(IEmployee handler, Guid orderId)
        {
            var order = Rep.Find(orderId);
            if (order.State != PurchaseOrder.PurchaseState.Purchasing)
            {
                return ReState.ArgError.Create("错误的订单状态");
            }
            order.State = PurchaseOrder.PurchaseState.Complete;
            AddPurchaseRecord(handler, order, PurchaseRecordType.StateChange);
            Rep.Update(order);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 添加采购单操作历史
        /// </summary>
        /// <param name="handler">操作人编号</param>
        /// <param name="order">采购单实体</param>
        /// <param name="type">采购单类型</param>
        /// <param name="msg">消息内容</param>
        private static void AddPurchaseRecord(IEmployee handler, PurchaseOrder order, PurchaseRecordType type, string msg = null)
        {
            PurchaseOrder.AddPurchaseRecord(handler, order, type, msg);

        }

        /// <summary>
        /// 设置重量和价格
        /// </summary>
        /// <param name="handlerId">操作人编号</param>
        /// <param name="purchase">采购单实体</param>
        /// <returns></returns>
        public IResultState SetWeightAndPrice(Guid handlerId, PurchaseOrder purchase)
        {
            var old = Rep.Find(purchase.Id);
            EmployeeBLL empBll = new EmployeeBLL();
            var emp = empBll.Details(handlerId);

            IResultState resultState = HandlePrice(purchase.Goodses, old);
            if (resultState != null) return resultState;

            resultState = HandleWeight(purchase.Goodses, old);
            if (resultState != null) return resultState;

            // 计算总价格          
            old.Total = old.Goodses.Sum(p => p.Price * p.Weight);

            // 计算总运费
            old.TotalWeight = old.Goodses.Sum(p => p.Weight);
            old.DeliveryPriceTotal = old.DeliveryPrice * old.TotalWeight;
            old.Records.Add(new PurchaseRecord()
            {
                Remarks = "订单商品价格和重量修改",
                Type = PurchaseRecordType.Edit,
                HandlerName = emp.Name
            });
            Rep.Update(old);
            return ReState.Success.Create();
        }

        /// <summary>
        /// 设置重量
        /// </summary>
        /// <param name="goodses">采购商品列表</param>
        /// <param name="old">采购单实体</param>
        /// <returns></returns>
        private IResultState HandleWeight(IEnumerable<PurchaseGoods> goodses, PurchaseOrder old)
        {
            foreach (var item in goodses)
            {
                var oldItem = old.Goodses.FirstOrDefault(p => p.Id == item.Id);
                if (oldItem == null)
                {
                    {
                        return ReState.ArgError.Create("错误商品信息");
                    }
                }
                oldItem.Weight = item.Weight;
            }
            return null;
        }

        /// <summary>
        /// 采购单取消
        /// </summary>
        /// <param name="handler">操作人编号</param>
        /// <param name="orderId">采购单编号</param>
        /// <returns></returns>
        public IResultState PurchaseCancel(IEmployee handler, Guid orderId)
        {
            var order = Rep.Find(orderId);
            //取消相关计划单
            if (order.PurchaseType == PurchaseType.Sale)
            {
                if (order.FromId == null)
                    return ReState.Error.Create("关联计划单信息出错");
                var fromId = Guid.Parse(order.FromId.ToString());
                orderBll.Cancel(fromId, handler.Id);
            }
            order.State = PurchaseOrder.PurchaseState.Cancel;
            AddPurchaseRecord(handler, order, PurchaseRecordType.StateChange);
            Rep.Update(order);
            return ReState.Success.Create();
        }
    }
}
